package com.zHan.system.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zHan.model.dto.AssginDeptDto;
import com.zHan.model.system.SysDept;
import com.zHan.model.system.SysUser;
import com.zHan.model.system.SysUserDept;
import com.zHan.system.exception.MyException;
import com.zHan.system.mapper.SysDeptMapper;
import com.zHan.system.mapper.SysUserDeptMapper;
import com.zHan.system.mapper.SysUserMapper;
import com.zHan.system.service.ISysDeptService;
import com.zHan.system.utils.DeptHelper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 组织机构 服务实现类
 * </p>
 *
 * @author zHan
 * @since 2023-06-24
 */
@Service
@Transactional
@Slf4j
public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> implements ISysDeptService {

    @Autowired
    private SysDeptMapper deptMapper;

    @Autowired
    private SysUserDeptMapper userDeptMapper;

    @Autowired
    private SysUserMapper sysUserMapper;


    /**
     * 部门列表（树形）
     *
     * @return
     */
    @Override
    public List<SysDept> selectNodes() {
        // 查询所有部门列表
        List<SysDept> sysDeptList =
                deptMapper.selectList(Wrappers.<SysDept>lambdaQuery().orderByAsc(SysDept::getSortValue));

        // 生成对应格式的列表
        List<SysDept> resultList = DeptHelper.buildTree(sysDeptList);

        return resultList;
    }

    /**
     * 递归删除
     *
     * @param id
     * @return
     */
    @Override
    public boolean removeDeptById(Long id) {
        // 查询当前删除部门下面是否有子部门，根据id是否对于parentId
        LambdaQueryWrapper<SysDept> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SysDept::getParentId, id);
        // 查询是否存在
        Integer count = deptMapper.selectCount(lambdaQueryWrapper);
        if (count > 0) {
            throw new MyException(201, "请先删除子部门");
        }
        //查询部门信息，确定是否可以删除
        LambdaQueryWrapper<SysDept> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .eq(SysDept::getStatus, 1)
                .eq(SysDept::getId, id);
        //不能删除，抛出业务异常
        if (this.getOne(queryWrapper) != null) {
            throw new MyException(201, "部门在启用状态，不能删除");
        }

        try {
            //先删除部门表中的信息
            this.removeById(id);
            //再删除其他表中的数据
            userDeptMapper.delete(Wrappers.<SysUserDept>lambdaQuery()
                    .eq(SysUserDept::getDeptId, id));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return true;
    }

    /**
     * 批量删除部门
     *
     * @param ids
     * @return
     */
    @Override
    public boolean batchRemoveDept(List<Long> ids) {
        for (Long id : ids) {
            // 查询当前删除部门下面是否有子部门，根据id是否对于parentId
            LambdaQueryWrapper<SysDept> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(SysDept::getParentId, id);
            // 查询是否存在
            Integer count = deptMapper.selectCount(lambdaQueryWrapper);
            if (count > 0) {
                throw new MyException(201, "请先删除子部门");
            }
        }
        //查询部门信息，确定是否可以删除
        LambdaQueryWrapper<SysDept> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .eq(SysDept::getStatus, 1)
                .in(SysDept::getId, ids);
        //不能删除，抛出业务异常
        if (this.count(queryWrapper) > 0) {
            throw new MyException(201, "有部门在启用状态，不能删除");
        }

        try {
            //先删除部门表中的信息
            this.removeByIds(ids);
            //再删除其他表中的数据
            userDeptMapper.delete(Wrappers.<SysUserDept>lambdaQuery()
                    .in(SysUserDept::getDeptId, ids));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return true;
    }

    /**
     * 根据id查询单个部门及其父节点集合
     *
     * @param id
     * @return
     */
    @Override
    public List<SysDept> selectNodesById(String id) {

        // 创建集合封装最终数据
        List<SysDept> resultList = new ArrayList<>();

        // 根据id查询单个部门
        SysDept sysDept = this.getById(id);
        if (sysDept == null) {
            return resultList;
        }
        String treePath = sysDept.getTreePath();
        if (StringUtils.isEmpty(treePath)) {
            return resultList;
        }
        String[] sysDeptIds = treePath.split(",");
        for (String sysDeptId : sysDeptIds) {
            SysDept dept = this.getById(sysDeptId);
            resultList.add(dept);
        }
        // 剔除第一个
        resultList.remove(0);
        // 生成对应格式的列表
        return resultList;
    }

    /**
     * 给用户分配部门
     *
     * @param assginDeptDto
     * @return
     */
    @Override
    public boolean assignDeptToUser(AssginDeptDto assginDeptDto) {
        // 获取对应的id
        String userId = assginDeptDto.getUserId();
        String deptId = assginDeptDto.getDeptId();

        // 查询用户，并修改
        SysUser sysUser = sysUserMapper.selectById(userId);
        sysUser.setDeptId(deptId);
        sysUser.setUpdateTime(new Date());
        sysUserMapper.updateById(sysUser);

        // 根据userId删除已分配的部门
        LambdaQueryWrapper<SysUserDept> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SysUserDept::getUserId, userId);
        userDeptMapper.delete(lambdaQueryWrapper);

        // 获取部门id，添加到用户部门关系表
        SysUserDept sysUserDept = new SysUserDept();
        sysUserDept.setUserId(userId);
        sysUserDept.setDeptId(deptId);
        userDeptMapper.insert(sysUserDept);

        return true;
    }

    /**
     * 获取用户的部门数据
     *
     * @param userId
     * @return
     */
    @Override
    public List<SysDept> selectDeptsByUserId(String userId) {
        // 获取所有部门，status=1
        LambdaQueryWrapper<SysDept> sysDeptLambdaQueryWrapper = new LambdaQueryWrapper<>();
        sysDeptLambdaQueryWrapper.eq(SysDept::getStatus, "1");
        List<SysDept> sysDeptList = deptMapper.selectList(sysDeptLambdaQueryWrapper);

        // 根据用户id，获取用户分配的部门列表
        LambdaQueryWrapper<SysUserDept> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(SysUserDept::getUserId, userId);
        List<SysUserDept> userDeptList = userDeptMapper.selectList(lambdaQueryWrapper);

        // 从第二步中，得到所有部门id
        List<String> deptList = new ArrayList<>();
        for (SysUserDept userDept : userDeptList) {
            deptList.add(userDept.getDeptId());
        }

        // 数据处理，isSelect ，选中为true，未选中为false
        // 拿着分配菜单 和 所有菜单比对，有相同的，isSelect为true
        for (SysDept sysDept : sysDeptList) {
            if (deptList.contains(sysDept.getId())) {
                sysDept.setSelect(true);
            } else {
                sysDept.setSelect(false);
            }
        }

        // 返回转换成树形结果，用MenuHelper的方法
        return DeptHelper.buildTree(sysDeptList);
    }

    /**
     * 新增部门
     *
     * @param sysDept
     * @return
     */
    @Override
    public boolean saveDept(SysDept sysDept) {
        // 补全treePath
        String treePath = fillTreePath(sysDept);
        sysDept.setUpdateTime(new Date());
        // 先执行新增方法
        deptMapper.insert(sysDept);
        // 获取id
        String id = sysDept.getId();
        // treePath 加上自己的id
        treePath = treePath + id + ",";
        sysDept.setTreePath(treePath);
        return deptMapper.updateById(sysDept) > 0;
    }

    /**
     * 补全treePath
     *
     * @param sysDept
     */
    private String fillTreePath(SysDept sysDept) {
        String parentId = sysDept.getParentId();
        List<String> treePathList = new ArrayList<>();
        while (!parentId.equals("0")) {
            treePathList.add(0, parentId);
            parentId = this.getById(parentId).getParentId();
        }
        // 转换成字符串
        String treePath = "," + String.join(",", treePathList) + ",";
        if (sysDept.getParentId().equals("0")) {
            return ",";
        }
        return treePath;
    }

    /**
     * 更改部门状态
     *
     * @param id
     * @param status
     * @return
     */
    @Override
    public boolean updateStatus(Long id, Integer status) {
        SysDept dept = deptMapper.selectById(id);
        dept.setStatus(status);
        return this.updateById(dept);
    }
}
